package
{
	import com.greensock.TweenLite;
	import com.greensock.plugins.TintPlugin;
	import com.greensock.plugins.TweenPlugin;
	import com.jac.mouse.MouseWheelEnabler;
	
	import events.ReaderEvent;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageDisplayState;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.Security;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	
	import model.ReaderModel;
	
	import service.ReaderService;
	
	import utils.ColorUtil;
	
	import view.ControlBar;
	import view.ui.PageCont;
	
	[SWF(width="830", height="710", frameRate="60", backgroundColor="0xffffff")]
	public class EmacleReader extends Sprite
	{
		/**
		 * 单例数据层 
		 */		
		private var _m:ReaderModel = ReaderModel.getInstance();
		/**
		 * 单例服务层 
		 */		
		private var _s:ReaderService = ReaderService.getInstance();
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 显示对象
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 * 顶部控制条 
		 */		
		private var _cb:ControlBar;
		
		/**
		 * 所有可视页的容器 
		 */		
		private var _cont:Sprite;
		/**
		 * _cont的显示父级 
		 */		
		private var _drawTarget:Sprite;
		
		private var _thumCanvas:Bitmap;
		private var _thumCanvasContext:BitmapData;
		private var _mtx:Matrix;
		private var _clearRec:Rectangle;
		
		private var _scrollBar:SKscroll_bar;
		private var _scrollBar_h:SKscroll_h;
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 页码相关变量
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 * 垂直滚动条距离顶端和底端的距离像素（水平滚动条亦然）
		 */		
		private static const SCROLL_PADDING:Number = 2;
		
		/**
		 * 文档模式，可见的开始页码 
		 */		
		private var _visiblePageSid:int = 1;
		
		/**
		 * 缩略图模式，可见的开始页码 
		 */		
		private var _visiblePageThumSid:int = 1;
		
		/**
		 * 所略图模式，可见的开始行数 
		 */		 
		private var _visiblePageThumSline:int = 1;
		
		/**
		 * 可见视图的滚动显示位置 
		 */		
		private var _view_y:Number = 0;
		
		/**
		 * 可见试图的滚动目标位置（用于处理试图滚动的缓动效果）
		 */		
		private var _targetView_y:Number = 0;
			
		/**
		 * 顶部控制条的高度
		 */		
		private var _barHeight:Number = 44;
		
		/**
		 * 可视区域的高度，默认为舞台高减去顶部控制bar的高，在容器缩放后，这个可视区域会变化 
		 */		
		private var _visibleHeight:Number;
		
		/**
		 * 可试区域的宽度，为舞台宽度 
		 */		
		private var _visibleWidth:Number;
		
		private var _pagesAdded:Array = [];
		
		private var _ydelta:Number;
		
		private var _isDraggingScrollBar:Boolean = false;
		
		private var _allLoaded:Boolean = false;
		
		private var _draggingViewStartPoint:Point;
		private var _originalViewPoint:Point;
		
		private var _vScrollDelta:Number;
		private var _hScrollDelta:Number;
		
		/**
		 * 从所略图模式切换到普通模式用户点击的id 
		 */		
		private var _navFromListViewID:int = 0;
		
		/**
		 * 水平的位置比例 
		 */		
		private var _perH:Number;
		
		private var _mouse_delta:Number = 20;
		
		public function EmacleReader()
		{
			addEventListener(Event.ENTER_FRAME, checkStage);
		}
		
		private function checkStage(e:Event):void
		{
			if(stage.stageWidth > 0)
			{
				removeEventListener(Event.ENTER_FRAME, checkStage);
				initApp();			
				//if(ExternalInterface.available) ExternalInterface.call("alert", stage.stageHeight);
			}
		}
		
		private function initApp():void
		{
			MouseWheelEnabler.init(this.stage);
			MouseWheelEnabler.eventTimeout = 0;
//			MouseWheelEnabler.useRawValues = true;			
			Security.allowDomain("*");
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			var cm:ContextMenu = new ContextMenu();
			var mi:ContextMenuItem  = new ContextMenuItem("Emacle Reader v1.62");
			cm.hideBuiltInItems();
			cm.customItems.push(mi);
			this.contextMenu = cm;
			
			TweenPlugin.activate([TintPlugin]);
			
			parseFlashVars();
			initUI();
			addListeners();
			onStageResize();	
			//addJSCallback();
			
			_m.targetWidth = stage.stageWidth;
			_m.targetHeight = stage.stageHeight - _barHeight;//这两句设置不能颠倒，否则会有问题
			_visibleHeight = _m.targetHeight;
			_visibleWidth = _m.targetWidth;
			
			_ydelta = _m.totalHeight;		
			onViewModeChanged();
		}
		
		private function addJSCallback():void
		{
			if(ExternalInterface.available) ExternalInterface.addCallback("resetFileInfo", resetFileInfo);
		}
		
		/**
		 * 供js调用，用于重新更换文件， 
		 * @param fileurl
		 * @param total_page_num
		 * 
		 */		
		public function resetFileInfo(fileurl:String, total_page_num:Number):void
		{
			removeEventListener(Event.ENTER_FRAME, render);
			removeEventListener(Event.ENTER_FRAME, renderThumbs);			
			_m.destroy();
		}
		
		private function parseFlashVars(): void
		{
			var obj:Object = this.loaderInfo.parameters;
			if(obj["logo_uri"] != null) _m.style.logo_uri = obj["logo_uri"];
			if(obj["logo_x"] != null) _m.style.logo_x = obj["logo_x"];
			if(obj["logo_y"] != null) _m.style.logo_y = obj["logo_y"];
			
			if(obj["top_bar_bg_color"] != null) _m.style.top_bar_bg_color = ColorUtil.getColorFromRGB16(obj["top_bar_bg_color"]);
			if(obj["bg_color"] != null) _m.style.bg_color = ColorUtil.getColorFromRGB16(obj["bg_color"]);
			if(obj["btn_out_color"] != null) _m.style.btn_out_color = ColorUtil.getColorFromRGB16(obj["btn_out_color"]);
			if(obj["btn_over_color"] != null) _m.style.btn_over_color = ColorUtil.getColorFromRGB16(obj["btn_over_color"]);
			if(obj["btn_down_color"] != null) _m.style.btn_down_color = ColorUtil.getColorFromRGB16(obj["btn_down_color"]);
			if(obj["btn_disable_color"] != null) _m.style.btn_disable_color = ColorUtil.getColorFromRGB16(obj["btn_disable_color"]);
			if(obj["scroll_bar_color"] != null) _m.style.scroll_bar_color = ColorUtil.getColorFromRGB16(obj["scroll_bar_color"]);
			
			if(obj["scales"] != null) _m.style.scales = String(obj["scales"]).split(",");
			if(obj["thumbCounts"] != null) _m.style.thumbCounts = String(obj["thumbCounts"]).split(",");		
			if(obj["api_base"] != null) ReaderService.API_BASE = obj["api_base"];
			if(obj["io_check"] != null) _m.style.io_check = int(obj["io_check"]);
			if(obj["io_message"] != null) _m.style.io_message = obj["io_message"];
			if(obj["show_print"] != null) _m.style.show_print = int(obj["show_print"]) == 1;
			if(obj["logo_link"] != null) _m.style.logo_link = obj["logo_link"];
			
			if(obj["jsHandler"] != null)
			{
				var str_api:String  = obj["jsHandler"];
				if(str_api.indexOf("(") >= 0 || str_api.indexOf("%28") >= 0)
				{
					if(ExternalInterface.available) ExternalInterface.call("alert", "jsHandler包含非法字符!");
				}else{
					ReaderService.JS_API = obj["jsHandler"];
				}
			}else{
				if(ExternalInterface.available) ExternalInterface.call("alert", "初始化缺少jsHandler参数，内部将使用alert报错");
			}
			
//			_m.file_url = "http://www.tongbupan.com/review/file/previewload/wenliang.yang@emacle.com/test.txt/?v=1339553156140";
//			_s.getToken();
//			_m.file_url = "https://www.tongbupan.com/review/file/previewload/chao5_002@126.com/paper0778-burke.pdf?v=1336989535556";					
//			_m.total_page_num = 10;
//			return;		
//			if(ExternalInterface.available) ExternalInterface.call("alert", "!!!6");
			
			if(obj["fileurl"] != null)
			{
				//站内
				_m.file_url = obj["fileurl"];
				if(obj["total_page_num"]!= null) _m.total_page_num = obj["total_page_num"];
				else ExternalInterface.call("alert", "缺少初始化参数(站内)：total_page_num（总页数)");
			}else{
				if(obj["linkid"] != null) _s.linkid = obj["linkid"];
				else if(ExternalInterface.available) ExternalInterface.call("alert", "缺少初始化参数(站外)：linkid");
				if(obj["version"] != null) _s.version = obj["version"];
				if(obj["path"] != null) _s.path = obj["path"];
				if(obj["split"] != null) _s.split = obj["split"];
				_m.isLinkMode = true;
				//站外
				_s.getToken();
			}
		}
		
		private function initUI():void
		{
			_drawTarget = new Sprite();
			_cont = new Sprite();
			_drawTarget.addChild(_cont);
			_drawTarget.visible = false;
			addChild(_drawTarget);
			
			_thumCanvasContext = new BitmapData(stage.stageWidth, stage.stageHeight - _barHeight);
			_thumCanvas = new Bitmap(_thumCanvasContext);
			_thumCanvas.y = _barHeight;
			addChild(_thumCanvas);
			
			_mtx = new Matrix();
			_clearRec = new Rectangle(0,0,stage.stageWidth, stage.stageHeight - _barHeight);
			
			_cb = new ControlBar();
			addChild(_cb);	
			_scrollBar = new SKscroll_bar();
			TweenLite.to(_scrollBar, 0, {tint:_m.style.scroll_bar_color});
			addChild(_scrollBar);		
			_scrollBar_h = new SKscroll_h();
			TweenLite.to(_scrollBar_h, 0, {tint:_m.style.scroll_bar_color});
			addChild(_scrollBar_h);
		}
		
		private function addListeners():void
		{
			_m.addEventListener(ReaderEvent.VIEW_MODE_CHANGED, onViewModeChanged);
			_m.addEventListener(ReaderEvent.VIEW_SCALE_CHANGED, onViewScaleChanged);
			_m.addEventListener(ReaderEvent.VIEW_THUMB_COUNTS_CHANGED, onViewThumbCountsChanged);
			_m.addEventListener(ReaderEvent.JUMP_PAGE, onJumpPage);
			_m.addEventListener(ReaderEvent.PAGE_REFRESH, onPageRefresh);
			_m.addEventListener(ReaderEvent.PAGE_LOADED, onPageLoaded);
			
			_scrollBar.addEventListener(MouseEvent.MOUSE_DOWN, onScrollBarMouseDown);
			_scrollBar_h.addEventListener(MouseEvent.MOUSE_DOWN, onScrollBarHMouseDown);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
			stage.addEventListener(MouseEvent.CLICK, onNavToPageFromListView);
			stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
			stage.addEventListener(Event.RESIZE, onStageResize);	
		}
		
		protected function onPageLoaded(event:Event):void
		{
			_m.removeEventListener(ReaderEvent.PAGE_LOADED, onPageLoaded);
			onStageResize();
		}
		
		/**
		 * 所略图模式，点击某个，返回普通模式，并显示该页 
		 * @param event
		 * 
		 */		
		protected function onNavToPageFromListView(e:MouseEvent):void
		{
			if(_m.viewMode == 0) return;
			if(stage.mouseY < _barHeight) return;
			if(stage.mouseX > _visibleWidth - 10) return;
			if(_m.block) return;
			
			var posx:Number = stage.mouseX;
			var posy:Number = stage.mouseY + _view_y - _barHeight;
			
			var in_l:int = Math.floor(posy / (_m.thumbHeight + _m.padding_v)) + 1;
			var in_r:int = Math.floor(posx / (_m.thumbWidth + _m.padding_h)) + 1;
			
			var id:int = (in_l - 1) * _m.style.thumbCounts[_m.thumbCountsID] + in_r;
			if(id > _m.total_page_num) return;			
			_navFromListViewID = id;
			_m.viewMode = 0;
		}		
		
		protected function onStopRenderTimer(e:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, onStopRenderTimer);
			removeEventListener(Event.ENTER_FRAME, render);
			removeEventListener(Event.ENTER_FRAME, renderThumbs);
		}
		
		protected function onJumpPage(e:ReaderEvent):void
		{
			_targetView_y = _view_y = (e.data.pid - 1) * Math.round((_m.onePageHeight + _m.padding_v)* _m.viewScale) ;
			_allLoaded = false;
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
		}
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 鼠标滚动，拖动操作，及键盘
		///////////////////////////////////////////////////////////////////////////////////////////////////
		protected function onMouseWheel(event:MouseEvent):void
		{
			if(_m.block) return;
			
//			trace(">>>" + event.delta);
			var de:Number = event.delta;
			if(de > 0) de = _mouse_delta;
			else if(de < 0) de = - _mouse_delta;
			
			_targetView_y -= de * _m.scroll_speed;
			if(_targetView_y > _m.totalHeight - _visibleHeight) _targetView_y = _m.totalHeight - _visibleHeight;
			if(_targetView_y < 0) _targetView_y = 0;
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
			else addEventListener(Event.ENTER_FRAME, renderThumbs);
		}
		
		protected function onStageMouseDown(e:MouseEvent):void
		{
			if(_m.viewMode == 1) return;
			if(_m.block) return;
			if(stage.mouseY > _barHeight && stage.mouseX < _visibleWidth - 20 && stage.mouseY < stage.stageHeight - 20)
			{
				//此时说明需要拖拽视图
				_originalViewPoint = new Point(_cont.x, _view_y);
				_draggingViewStartPoint = new Point(stage.mouseX, stage.mouseY);
				addEventListener(Event.ENTER_FRAME, draggingView);
				stage.addEventListener(MouseEvent.MOUSE_UP, stopDraggingView);
			}
		}
		
		private function draggingView(e:Event):void
		{
			var deltax:Number = stage.mouseX - _draggingViewStartPoint.x;
			var deltay:Number = stage.mouseY - _draggingViewStartPoint.y;
			
			var pw:Number = _m.onePageWidth * _m.viewScale;
			if(_visibleWidth < pw && _m.viewMode == 0)
			{
				var tx:Number = _originalViewPoint.x + deltax;
				if(tx > 0) tx = 0;
				if(tx < _visibleWidth - pw) tx = _visibleWidth - pw;
				_cont.x = tx;
			}
			
			var ty:Number = _originalViewPoint.y - deltay;
			if(ty > _m.totalHeight - _visibleHeight) ty = _m.totalHeight - _visibleHeight;
			if(ty < 0) ty = 0;
			_view_y = _targetView_y = ty;
			
			_allLoaded = false;
			if(_m.viewMode == 0) render();
			else renderThumbs();
		}
		
		private function stopDraggingView(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME, draggingView);
			stage.removeEventListener(MouseEvent.MOUSE_UP, stopDraggingView);
		}
		
		protected function onStageKeyDown(e:KeyboardEvent):void
		{
			if(_m.block) return;
			switch(e.keyCode)
			{
				case 33:
					// Pg UP
					if(_m.viewMode == 0) _m.jumpToPage(_m.current_page - 1);
					else{
						
					}
					break;
				case 34:
					// Pg Down
					if(_m.viewMode == 0) _m.jumpToPage(_m.current_page + 1);
					else{
						
					}
					break;
				case 36:
					// Home
					if(_m.viewMode == 0) _m.jumpToPage(1);
					else{
						
					}
					break;
				case 35:
					// End
					if(_m.viewMode == 0) _m.jumpToPage(_m.total_page_num);
					else{
						
					}
					break;
				case 37:
					//左
					if(_m.viewMode == 0) _m.jumpToPage(_m.current_page - 1);
					else{
						
					}
					break;
				case 39:
					//右
					if(_m.viewMode == 0) _m.jumpToPage(_m.current_page + 1);
					else{
						
					}
					break;
				case 38:
					//上
					_targetView_y -= 4 * _m.scroll_speed;
					if(_targetView_y > _m.totalHeight - _visibleHeight) _targetView_y = _m.totalHeight - _visibleHeight;
					if(_targetView_y < 0) _targetView_y = 0;
					if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
					else addEventListener(Event.ENTER_FRAME, renderThumbs);
					break;
				case 40:
					//下
					_targetView_y += 4 * _m.scroll_speed;
					if(_targetView_y > _m.totalHeight - _visibleHeight) _targetView_y = _m.totalHeight - _visibleHeight;
					if(_targetView_y < 0) _targetView_y = 0;
					if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
					else addEventListener(Event.ENTER_FRAME, renderThumbs);
					break;
			}
		}
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 阅读模式切换
		///////////////////////////////////////////////////////////////////////////////////////////////////
		protected function onPageRefresh(e:ReaderEvent):void
		{
			while(_cont.numChildren > 0) _cont.removeChildAt(0);
			_thumCanvasContext = new BitmapData(stage.stageWidth, stage.stageHeight - _barHeight);
			_thumCanvas.bitmapData = _thumCanvasContext;
			_pagesAdded = [];
			_allLoaded = false;
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
			else addEventListener(Event.ENTER_FRAME, renderThumbs);
		}
		
		protected function onViewThumbCountsChanged(e:ReaderEvent):void
		{
			var thumcounts:int = _m.style.thumbCounts[_m.thumbCountsID];
			_visiblePageSid = (_visiblePageThumSline - 1) * thumcounts + 1;
			var slien:int = Math.ceil(_visiblePageSid / thumcounts);
			
			_visiblePageThumSline = slien;
			
			while(_cont.numChildren > 0) _cont.removeChildAt(0);
			_visibleHeight = _m.targetHeight;
			_pagesAdded = [];
			_cont.scaleX = _cont.scaleY = 1;
			_cont.x = 0;
			
			_view_y = _targetView_y = (slien - 1) * _m.thumbHeight + slien * _m.padding_v;
			if(_view_y > _m.totalHeight - _visibleHeight) _view_y = _m.totalHeight - _visibleHeight;
			if(_view_y < 0) _view_y = 0;
			_targetView_y = _view_y;
			
			refreshBarHeight();
			
			_allLoaded = false;			
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
			else addEventListener(Event.ENTER_FRAME, renderThumbs);
		}
		
		protected function onViewScaleChanged(event:ReaderEvent = null):void
		{
			if(_m.viewMode != 0) return;
			removeEventListener(Event.ENTER_FRAME, render);
			
			var ydelta:Number = _m.totalHeight;
			var dd:Number = (ydelta - _ydelta) * _view_y / _ydelta;
			if(isNaN(dd)) return;
			
			_ydelta = ydelta;
			_view_y += dd;
			
			if(_view_y > _m.totalHeight - _visibleHeight) _view_y = _m.totalHeight - _visibleHeight;
			if(_view_y < 0) _view_y = 0;
			_targetView_y = _view_y;
			
			_cont.scaleX = _cont.scaleY = _m.viewScale;
			if(isNaN(_perH))
			{
				var centerx:Number = stage.stageWidth * 0.5 - _m.onePageWidth * 0.5 * _m.viewScale;
				_cont.x = centerx;
			}else{
				_cont.x = -_perH * (_m.onePageWidth *_m.viewScale - _visibleWidth);
			}
			
			refreshBarHeight();
			refreshHBarWidth();
			
			addEventListener(Event.ENTER_FRAME, render);
		}
		
		protected function onViewModeChanged(event:ReaderEvent = null):void
		{
			var thumcounts:int = _m.style.thumbCounts[_m.thumbCountsID];
			if(_m.viewMode == 0)
			{
				removeEventListener(Event.ENTER_FRAME, renderThumbs);
				while(_cont.numChildren > 0) _cont.removeChildAt(0);
				var sid:int = _navFromListViewID;
				if(sid== 0) sid = (_visiblePageThumSline - 1) * thumcounts + 1;
				_view_y = (sid - 1) * (_m.onePageHeight + _m.padding_v);
				if(_view_y > _m.totalHeight - _visibleHeight) _view_y = _m.totalHeight - _visibleHeight;
				if(_view_y < 0) _view_y = 0;
				_targetView_y = _view_y + 1;
				_pagesAdded = [];
				_ydelta = _m.totalHeight;
				_allLoaded = false;
				_navFromListViewID = 0;
				addEventListener(Event.ENTER_FRAME, render);			
			}else{
				var slien:int = Math.ceil(_visiblePageSid / thumcounts);
				_visiblePageThumSline = slien;
				removeEventListener(Event.ENTER_FRAME, render);	
				while(_cont.numChildren > 0) _cont.removeChildAt(0);
				_visibleHeight = _m.targetHeight;
				_pagesAdded = [];
				_cont.scaleX = _cont.scaleY = 1;
				_cont.x = 0;		
				_view_y = _targetView_y = (slien - 1) * _m.thumbHeight + slien * _m.padding_v;
				if(_view_y > _m.totalHeight - _visibleHeight) _view_y = _m.totalHeight - _visibleHeight;
				if(_view_y < 0) _view_y = 0;
				_targetView_y = _view_y;
				
				_allLoaded = false;
				addEventListener(Event.ENTER_FRAME, renderThumbs);	
			}
			refreshBarHeight();
			refreshHBarWidth();
		}
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 位置更新排版，包括全屏模式切换都会触发此事件
		///////////////////////////////////////////////////////////////////////////////////////////////////
		protected function onStageResize(event:Event = null):void
		{
			removeEventListener(Event.ENTER_FRAME, render);
			removeEventListener(Event.ENTER_FRAME, renderThumbs);
			
			_cb.layout();
			this.graphics.clear();
			this.graphics.beginFill(_m.style.bg_color);
			this.graphics.drawRect(0,0,stage.stageWidth, stage.stageHeight);
			this.graphics.endFill();	
			
			_m.targetWidth = stage.stageWidth;
			_m.targetHeight = stage.stageHeight - _barHeight;
			
			_visibleHeight = _m.targetHeight;
			_visibleWidth = _m.targetWidth;
			_clearRec = new Rectangle(0,0,stage.stageWidth, stage.stageHeight - _barHeight);
			
			if(_m.viewMode == 0)
			{
				for(var i:int = 0, len:int = _cont.numChildren ; i < len; i ++)
				{
					var p:PageCont = _cont.getChildAt(i) as PageCont;
					var cid:int = p.pid;
					var ty:Number = (cid - 1) * (_m.onePageHeight + _m.padding_v);
					p.scaleTo(_m.sourceScale, true);
					p.x = 0;
					p.y = ty;
				}
				onViewScaleChanged();
			}else{
				var thumcounts:int = _m.style.thumbCounts[_m.thumbCountsID];
				for(i = 0, len = _cont.numChildren ; i < len; i ++)
				{
					p = _cont.getChildAt(i) as PageCont;
					cid = p.pid;
					var p_l:int = Math.ceil(cid/ thumcounts);
					var p_r:int = (cid - 1) % thumcounts + 1;
					
					var tx:Number = (p_r - 1) * ( _m.thumbWidth + _m.padding_h );
					ty = (p_l - 1) * (_m.thumbHeight + _m.padding_v);
					p.scaleTo(_m.sourceScaleThumb, true);
					p.y = ty;
					p.x = tx;
				}
			}
			
			_thumCanvasContext = new BitmapData(stage.stageWidth, stage.stageHeight - _barHeight);
			_thumCanvas.bitmapData = _thumCanvasContext;
			
			_scrollBar.x = stage.stageWidth - 8;	
			_scrollBar_h.x = 0;
			_scrollBar_h.y = stage.stageHeight - 13;
			
			refreshBarHeight();
			refreshHBarWidth();
			setScrollBarStatus();
			
			if(_view_y > _m.totalHeight - _visibleHeight) _view_y = _m.totalHeight - _visibleHeight;
			if(_view_y < 0) _view_y = 0;
			_targetView_y = _view_y;		
			_allLoaded = false;			
			
			_mouse_delta = (stage.displayState == StageDisplayState.FULL_SCREEN) ? 20 : 10;
//			trace("_mouse_delta::" + _mouse_delta);
			
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
			else addEventListener(Event.ENTER_FRAME, renderThumbs);
		}		

		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 滚动条相关逻辑
		///////////////////////////////////////////////////////////////////////////////////////////////////
		protected function onScrollBarHMouseDown(e:MouseEvent):void
		{
			_isDraggingScrollBar = true;
			stage.addEventListener(MouseEvent.MOUSE_UP, onStopDraggingScrollBarH);
			_hScrollDelta = _scrollBar_h.mouseX * _scrollBar_h.scaleX;
			addEventListener(Event.ENTER_FRAME, onDraggingScrollBarH);
		}
		
		protected function onStopDraggingScrollBarH(e:MouseEvent):void
		{
			_scrollBar_h.stopDrag();
			stage.removeEventListener(MouseEvent.MOUSE_UP, onStopDraggingScrollBarH);
			removeEventListener(Event.ENTER_FRAME, onDraggingScrollBarH);
			_isDraggingScrollBar = false;
		}
		
		protected function onDraggingScrollBarH(e:Event):void
		{
			var tx:Number = stage.mouseX - _hScrollDelta;
			if(tx < SCROLL_PADDING) tx = SCROLL_PADDING;
			if(tx > _visibleWidth - _scrollBar_h.width - SCROLL_PADDING) tx = _visibleWidth - _scrollBar_h.width - SCROLL_PADDING;
			_scrollBar_h.x = tx;		
			var perh:Number = (_scrollBar_h.x - SCROLL_PADDING)/ (_visibleWidth - _scrollBar_h.width - 2 * SCROLL_PADDING);
			_cont.x =  - (_m.onePageWidth *_m.viewScale - _visibleWidth) * perh;
			_allLoaded = false;
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
		}
		
		protected function onScrollBarMouseDown(e:MouseEvent):void
		{
			_isDraggingScrollBar = true;
			_vScrollDelta = _scrollBar.mouseY * _scrollBar.scaleY;
			stage.addEventListener(MouseEvent.MOUSE_UP, onStopDraggingScrollBar);
			addEventListener(Event.ENTER_FRAME, onDraggingScrollBar);
		}
		
		private function onDraggingScrollBar(e:Event):void
		{
			var ty:Number = stage.mouseY - _vScrollDelta;
			if(ty < _barHeight + SCROLL_PADDING) ty = _barHeight + SCROLL_PADDING;
			if(ty > stage.stageHeight - _scrollBar.height - SCROLL_PADDING) ty = stage.stageHeight - _scrollBar.height - SCROLL_PADDING;
			_scrollBar.y = ty;
			
			var per:Number = (_scrollBar.y - _barHeight - SCROLL_PADDING)/ (_visibleHeight - _scrollBar.height - 2 * SCROLL_PADDING);
			_view_y = _targetView_y = per * (_m.totalHeight - _visibleHeight);
			_allLoaded = false;
			if(_m.viewMode == 0) addEventListener(Event.ENTER_FRAME, render);
			else addEventListener(Event.ENTER_FRAME, renderThumbs);
		}
		
		protected function onStopDraggingScrollBar(e:MouseEvent):void
		{	
			_scrollBar.stopDrag();
			stage.removeEventListener(MouseEvent.MOUSE_UP, onStopDraggingScrollBar);
			removeEventListener(Event.ENTER_FRAME, onDraggingScrollBar);
			_isDraggingScrollBar = false;
		}
		
		private function refreshBarHeight():void
		{
			if(_visibleHeight > _m.totalHeight)
			{
				_scrollBar.visible = false;
				return;
			}
			
			var sh:Number = (_visibleHeight / _m.totalHeight) * _visibleHeight;
			if(sh <  60) sh = 60;
			if(sh > 300) sh = 300;
			_scrollBar.height = sh;	
			_scrollBar.visible = true;
		}
		
		private function refreshHBarWidth():void
		{
			if(_visibleWidth >= _m.onePageWidth *_m.viewScale)
			{
				_scrollBar_h.visible = false;
				return;
			}
			var sw:Number = (_visibleWidth / (_m.onePageWidth * _m.viewScale)) * _visibleWidth;
			if(sw < 60) sw = 60;
			if(sw > 300) sw = 300;
			_scrollBar_h.width = sw;
			_scrollBar_h.visible = true;
		}
		
		private function setScrollBarStatus():void
		{
			if(_isDraggingScrollBar) return;
			var per:Number = _view_y / (_m.totalHeight - _visibleHeight);
			_scrollBar.y = _barHeight + SCROLL_PADDING + (_visibleHeight - 2 * SCROLL_PADDING - _scrollBar.height) * per;
			
			var perh:Number = -_cont.x / (_m.onePageWidth *_m.viewScale - _visibleWidth);
			_scrollBar_h.x =  SCROLL_PADDING + (_visibleWidth - 2 * SCROLL_PADDING - _scrollBar_h.width ) * perh;
			_perH = perh;
		}
		
		///////////////////////////////////////////////////////////////////////////////////////////////////
		/////// 两种阅读模式的核心渲染部分 render: 普通模式渲染， renderThumb：所略图模式渲染
		///////////////////////////////////////////////////////////////////////////////////////////////////
		private function render(e:Event = null):void
		{
			_view_y += (_targetView_y - _view_y) * 0.15;
			if(Math.abs(_view_y - _targetView_y) < 1) _view_y = _targetView_y;
			_visiblePageSid = Math.floor((_view_y + _visibleHeight * 0.5) / Math.round((_m.onePageHeight + _m.padding_v)* _m.viewScale)) + 1;
			
			var tempVPSid:int = _visiblePageSid - 1;
			if(tempVPSid < 1) tempVPSid = 1;
					
			_cb.setPageInfo(_visiblePageSid);
			
			_thumCanvasContext.fillRect(_clearRec, _m.style.bg_color);			
			_mtx.ty = -_view_y;
			_thumCanvasContext.draw(_drawTarget, _mtx);
			
			setScrollBarStatus();
			
			if(_allLoaded)
			{
				if(_view_y == _targetView_y) addEventListener(Event.ENTER_FRAME, onStopRenderTimer);
			}else{
				var needtoload:int = _pagesAdded.length;
				var loadedcount:int = 0;
				
				for(i = 0 ; i < needtoload ; i ++)
				{
					var p:PageCont = _m.getPage(_pagesAdded[i]) as PageCont;
					if(p.loaded) loadedcount += 1;
				}
				_allLoaded = (needtoload == loadedcount);
			}
			
			if(_pagesAdded.length == _m.total_page_num)
			{
//				trace(">>>>>>> all loaded!!!");
				return;
			}
			
			for(var i:int = 0, len:int = _pagesAdded.length ; i < len ; i ++)
			{
				p = _m.getPage(_pagesAdded[i]) as PageCont;
				if(!p.loaded)
				{
					if(p.pid < tempVPSid || p.pid > tempVPSid + _m.onePageVisibleAmount + 2)
					{
//						trace("page removed:::" + p.pid);
						_pagesAdded.splice(i, 1);
						i -= 1;
						len -= 1;
						_cont.removeChild(p);
					}					
				}
			}
			
			for(i = 0; i < _m.onePageVisibleAmount + 2; i ++)
			{
				var cid:int = tempVPSid + i;
				var ty:Number = (cid - 1) * (_m.onePageHeight + _m.padding_v);
				if(_pagesAdded.indexOf(cid) < 0  &&  cid <= _m.total_page_num )
				{
					p = _m.getPage(cid) as PageCont;
					p.scaleTo(_m.sourceScale, true);
					p.tw = _m.org_width;
					p.th = _m.org_height;
					p.x = 0;
					p.y = ty;
					_cont.addChild(p);
					_pagesAdded[_pagesAdded.length] = cid;
					_allLoaded = false;
				}
			}	
		}//render end
		
		private function renderThumbs(e:Event = null):void
		{
			_view_y += (_targetView_y - _view_y) * 0.15;
			if(Math.abs(_view_y - _targetView_y) < 1) _view_y = _targetView_y;
			
			_thumCanvasContext.fillRect(_clearRec, _m.style.bg_color);
			_mtx.ty = -_view_y;
			_thumCanvasContext.draw(_drawTarget, _mtx);
			
			var thumcounts:int = _m.style.thumbCounts[_m.thumbCountsID];	
			_visiblePageThumSline = Math.floor(_view_y / (_m.thumbHeight + _m.padding_v)) + 1;		
			setScrollBarStatus();
			
			if(_allLoaded)
			{
				if(_view_y == _targetView_y) addEventListener(Event.ENTER_FRAME, onStopRenderTimer);
			}else{
				var needtoload:int = _pagesAdded.length;
				var loadedcount:int = 0;
				
				for(i = 0 ; i < needtoload ; i ++)
				{
					p = _m.getPage(_pagesAdded[i]) as PageCont;
					if(p.loaded) loadedcount += 1;
				}
				_allLoaded = (needtoload == loadedcount && _pagesAdded.length > 0);
			}
			
			if(_pagesAdded.length == _m.total_page_num) return;
			
			var tempVPSid:int = (_visiblePageThumSline - 1) * thumcounts + 1;
			for(var i:int = 0, len:int = _pagesAdded.length ; i < len ; i ++)
			{
				p = _m.getPage(_pagesAdded[i]) as PageCont;
				if(!p.loaded)
				{
					if(p.pid < tempVPSid || p.pid > tempVPSid + _m.onePageVisibleAmountThumb)
					{
//						trace("page removed:::" + p.pid);
						_pagesAdded.splice(i, 1);
						i -= 1;
						len -= 1;
						_cont.removeChild(p);
					}					
				}
			}
			
			
			for(i = 0; i < _m.onePageVisibleThumblines; i ++)
			{
				for(var j:int = 0; j < thumcounts ; j ++)
				{
					var cid:int = (_visiblePageThumSline + i - 1) * thumcounts + j + 1;
					if(_pagesAdded.indexOf(cid) < 0 && cid <= _m.total_page_num && cid > 0)
					{
						var tx:Number = j * ( _m.thumbWidth + _m.padding_h );
						var ty:Number = (i + _visiblePageThumSline - 1) * (_m.thumbHeight + _m.padding_v);
						var p:PageCont = _m.getPage(cid) as PageCont;
						p.scaleTo(_m.sourceScaleThumb, true);
						p.y = ty;
						p.x = tx;
						_cont.addChild(p);
						_pagesAdded[_pagesAdded.length] = cid;
						_allLoaded = false;
					}
				}				
			}
		}//renderThumbs end
		
	}	
}